home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-09-02 | 6.4 KB | 157 lines | [TEXT/CCL2] |
- ;;;-*- Mode: Lisp; Package: CCL -*-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; split-lfun.lisp
- ;; Code to split an lfun into pieces that WOOD knows how to save
- ;;
- ;; Copyright © 1992 Apple Computer, Inc. All rights reserved.
- ;; Permission is given to use, copy, and modify this software provided
- ;; that this copyright notice is attached to all derivative works.
- ;; This software is provided "as is". Apple makes no warranty or
- ;; representation, either express or implied, with respect to this software,
- ;; its quality, accuracy, merchantability, or fitness for a particular
- ;; purpose.
- ;;
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; Modification History
- ;;
- ;; -------------- 0.5
- ;; 03/13/92 bill New file
- ;;
-
- (in-package :ccl)
-
- (export '(split-lfun join-lfun))
-
- (eval-when (:compile-toplevel :execute)
- (require :lispequ))
-
- ; Returns a list of length five: (imms icode linkmap bits attrib fasl-version)
- ; If you APPLY JOIN-LFUN to this list, you will get a copy of the lfun.
- ; Note that the icode & linkmap vectors are of type (array (unsigned-byte 16)).
- ; ccl::%make-lfun requires that they be of exactly that type.
- ; Code largely copied from fasl-dump-lfun-vector.
- ; Tested in 2.0f3c2
-
- (defun split-lfun (lfun)
- (let* ((lfunv (%lfun-vector lfun))
- (lfunv-len (uvsize lfunv))
- icode
- (imm-count (%count-immrefs lfunv))
- (imms nil)
- (linkmap (make-array (ash imm-count 1)
- :element-type '(signed-byte 16)
- :initial-element $lm_longimm))
- (bits (lfun-bits lfun))
- (attrib (lfun-attributes lfun)))
- (declare (fixnum lfunv-len imm-count))
- (if (logbitp $lfatr-slfunv-bit attrib)
- ; swappable lfun-vectors have an extra longword at the end
- (decf lfunv-len 2))
- ; Skip the immediate map at the end of the lfun vector.
- (do ((i (1- lfunv-len) (1- i)))
- ((< i 0) (error "Immediate map took entire lfun"))
- (decf lfunv-len)
- (let ((word (uvref lfunv i)))
- (declare (fixnum word))
- (if (or (eql 0 (logand #xff word))
- (eql 0 (logand #xff00 word)))
- (return))))
- (decf lfunv-len (/ $t_lfun 2)) ; skip the header.
- (setq icode (make-array lfunv-len :element-type '(signed-byte 16)))
- (do ((i 0 (1+ i))
- (j (/ $t_lfun 2) (1+ j))
- (immno -1)
- (u-imm-count 0))
- ((>= i lfunv-len) (setq imm-count u-imm-count))
- (declare (fixnum i j))
- (if (%immref-p i lfunv)
- (multiple-value-bind (imm offset)
- (%nth-immediate lfunv (incf immno 1))
- (let ((first-imm (memq imm imms))
- (v-immno u-imm-count))
- (if first-imm
- (setq v-immno (length (cdr first-imm)))
- (progn
- (push imm imms)
- (incf u-imm-count)))
- (setf (aref icode i) (or offset 0))
- (setf (aref icode (1+ i)) v-immno)
- (setf (aref linkmap (+ immno immno))
- (%immediate-offset lfunv immno))
- (incf i)
- (incf j)))
- (setf (aref icode i) (uvref lfunv j))))
- (list (make-array imm-count :initial-contents (nreverse imms))
- icode linkmap bits attrib fasl-version)))
-
-
- (defvar *fasl-min-version* fasl-version)
- (defvar *fasl-max-version* fasl-version)
-
- ; imms is a sequence of Lisp values, preferably of type (array t)
- ; icode is an array of opcodes, preferably of type (array (unsigned-byte 16)).
- ; linkmap is alternating (byte) offsets in icode and
- ; $lm_longimm's, preferably of type (array (unsigned-byte 16)).
- ; bits is the LFUN-BITS of the function.
- ; attrib is its LFUN-ATTRIBUTES.
-
- ; At each linkmap referenced offset in icode, there are two (16-bit)
- ; words: a constant to add to the immediate (offsets a symbol to its
- ; value cell or function entry) and the index in IMMS for the immediate
- ; that goes there. This function just calls %MAKE-LFUN after coercing the
- ; sequences to the correct type and doing a little error checking.
-
- ; The list returned by split-lfun is taylor made to call join-lfun.
- ; (apply 'join-lfun (split-lfun #'split-lfun)) will get you a copy
- ; of #'split-lfun.
-
- (defun join-lfun (imms icode linkmap bits attrib &optional (fver fasl-version))
- (unless (<= *fasl-min-version* fver *fasl-max-version*)
- (cerror "they're compatible. Stop bothering me with error messages."
- "LFUN saved with FASL version #x~x, ~s is now #x~x."
- fver 'fasl-version fasl-version)
- (setq *fasl-min-version* (min fver *fasl-min-version*)
- *fasl-max-version* (max fver *fasl-max-version*)))
- (symbol-macrolet ((array-type '(array (signed-byte 16))))
- (let* ((imms (if (typep imms '(array t))
- imms
- (coerce imms '(array t))))
- (imms-length (length imms))
- (icode (if (typep icode array-type)
- icode
- (coerce icode array-type)))
- (icode-bytes (* 2 (length icode)))
- (linkmap (if (typep linkmap array-type)
- linkmap
- (coerce icode array-type)))
- (linkmap-length (length linkmap))
- (bits (require-type bits 'fixnum))
- (attrib (require-type attrib 'fixnum)))
- (unless (evenp linkmap-length)
- (error "~s has an odd number of elements." linkmap))
- (do ((i 0 (+ i 2)))
- ((>= i linkmap-length))
- (declare (fixnum i))
- (let ((offset (aref linkmap i))
- (type (aref linkmap (the fixnum (1+ i)))))
- (declare (fixnum offset))
- (unless (eql type $lm_longimm)
- (error "Type code ~s is not ~s" type $lm_longimm))
- (unless (and (evenp offset) (< -1 offset icode-bytes))
- (error "Offset ~s odd or out of range." offset))
- (setq offset (ash offset -1))
- (let ((sym-adjust (aref icode offset))
- (imms-index (aref icode (the fixnum (1+ offset)))))
- (declare (fixnum sym-adjust imms-index))
- (unless (and (< -1 imms-index imms-length)
- (or (eql sym-adjust 0)
- (and (symbolp (aref imms imms-index))
- (or (eql sym-adjust 8)
- (eql sym-adjust 16)))))
- (error "Malformed immediate specifier at index ~s in ~s"
- offset icode)))))
- (%make-lfun imms icode linkmap bits attrib))))